#ifndef QUAD_HPP_
#define QUAD_HPP_

#include "GaussHex.hpp"
#include "GaussTet.hpp"
#include <Eigen/Core>
#include <utility>

/* 标准四面体单元上的高斯积分 */
template <int order = 1> class TetQuad {
public:
  class Iterator {
    int pos;

  public:
    Iterator(int n) : pos(n) {}
    void operator++() { pos++; }
    // void operator --(){}
    std::pair<double, Eigen::Vector3d> operator*() const {
      return std::make_pair(
          QuadScheme::GaussTet::w[pos],
          Eigen::Vector3d{QuadScheme::GaussTet::q[3 * pos],
                          QuadScheme::GaussTet::q[3 * pos + 1],
                          QuadScheme::GaussTet::q[3 * pos + 2]});
    }
    // bool operator ==(const Iterator id){}
    bool operator!=(const Iterator id) { return this->pos != id.pos; }
  };

  Iterator begin() { return QuadScheme::GaussTet::offsets[order - 1]; }

  Iterator end() {
    if (order == QuadScheme::GaussTet::maxDegree) {
      return QuadScheme::GaussTet::n[QuadScheme::GaussTet::maxDegree - 1] +
             QuadScheme::GaussTet::offsets[QuadScheme::GaussTet::maxDegree - 1];
    } else {
      return QuadScheme::GaussTet::offsets[order];
    }
  }
};

/* 标准六面体上的高斯积分 */
template <int order = 1> class HexQuad {
public:
  class Iterator {
    int pos;

  public:
    Iterator(int n) : pos(n) {}
    void operator++() { pos++; }
    // void operator --(){}
    std::pair<double, Eigen::Vector3d> operator*() const {
      return std::make_pair(
          QuadScheme::GaussHex::w[pos],
          Eigen::Vector3d{QuadScheme::GaussHex::q[3 * pos],
                          QuadScheme::GaussHex::q[3 * pos + 1],
                          QuadScheme::GaussHex::q[3 * pos + 2]});
    }
    // bool operator ==(const Iterator id){}
    bool operator!=(const Iterator id) { return this->pos != id.pos; }
  };

  Iterator begin() { return QuadScheme::GaussHex::offsets[order - 1]; }

  Iterator end() {
    if (order == QuadScheme::GaussHex::maxDegree) {
      return QuadScheme::GaussHex::n[QuadScheme::GaussHex::maxDegree - 1] +
             QuadScheme::GaussHex::offsets[QuadScheme::GaussHex::maxDegree - 1];
    } else {
      return QuadScheme::GaussHex::offsets[order];
    }
  }
};

#endif